﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Collections;
namespace Littlebeer.Deduplicate.Functions
{
    public static class DeduplicateFunctionManager
    {
        public static string DoFunctions(string value, List<Deduplicate.Models.DeduplicateFunction> functions)
        {
            string result = value;
            if (functions != null)
            {
                foreach (Deduplicate.Models.DeduplicateFunction func in functions.OrderBy(d => d.Orders).Where(d => d.DeduplicateFunctionType == Deduplicate.Models.DeduplicateFunctionType.Single))
                {
                    result = DeduplicateFunctionFactory.GetFunction(func.FunctionName).DoFunction(result, func.Args);
                }
            }
            return result;
        }

        public static string DoMutiFunctions(string pk, IGrouping<object, DataRow> rows, Deduplicate.Models.DeduplicateRule rule)
        {
            string result = string.Join(",", rows.Select(d => d.Field<string>(pk)));//先把所有的ID都加一块（默认全部ID）
            List<string> ids = result.Split(',').ToList<string>();//把这些ID转成字符数组，用来进行集合运算

            //如果发现只剩一个了，就退出（如果现在已经只有一个了，那就没有必要再进行排除了，查重结果至少每组有两个才有意义）
            if (ids.Count() <= 1) return string.Join(",", ids);//退出循环，把这个唯一的返回出去

            //遍历所有包含多行处理函数的字段（就是没有进行分组的那些字段）
            foreach (var field in rule.DeduplicateRuleFields.Where(d => d.DeduplicateFunctions.Exists(s => s.DeduplicateFunctionType == Deduplicate.Models.DeduplicateFunctionType.Multiple)))
            {
                //先对这些字段进行单行函数处理，再做多行函数处理
                var query = from a in rows.AsParallel()
                            select new { id = a.Field<string>(pk), value = Littlebeer.Deduplicate.Functions.DeduplicateFunctionManager.DoFunctions(a.Field<string>(field.FieldName), field.DeduplicateFunctions) };

                //将处理的结果及ID存入一个HashTable，用来进行下一处理流程

                Hashtable MutiArgs = new Hashtable();
                query.ForAll(d =>
                {
                    if (!MutiArgs.ContainsKey(d.id))
                    {
                        //如果规则是自动规则，则如果值为空，自动跳过
                        if (rule.RuleType == Deduplicate.Models.DeduplicateRuleType.Auto && (d.value == null || d.value.Trim() == ""))
                        { 
                        
                        }
                        else
                        {
                            MutiArgs.Add(d.id, d.value);
                        }
                    }
                });

                //临时变量，记录当前字段结果集ID记录

                List<string> LeaveIDs = new List<string>();

                //遍历所有多行处理函数，逐个进行排除

                foreach (var func in field.DeduplicateFunctions.Where(d => d.DeduplicateFunctionType == Deduplicate.Models.DeduplicateFunctionType.Multiple))
                {

                    //临时变量，记录当前多行处理函数结果集ID记录

                    List<string> temp_ids = DeduplicateFunctionFactory.GetFunction(func.FunctionName).DoFunction(MutiArgs, func.Args).Split(',').Where(d => d != "").ToList<string>();

                    if (LeaveIDs.Count() == 0)
                    {
                        LeaveIDs = temp_ids;
                    }
                    else
                    {
                        //与本字段结果集求交集，舍弃不相交部分
                        LeaveIDs = LeaveIDs.Intersect(temp_ids).ToList<string>();
                    }
                    //如果当前字段结果集里只剩下一个了，其实也没有必要再往下执行了
                    if (LeaveIDs.Count() <= 1)
                    {
                        ids = ids.Intersect(LeaveIDs).ToList<string>();
                        return string.Join(",", ids);//退出循环，把这个唯一的返回出去
                    }
                }

                //将本字段多行处理后符合要求的结果与原来整体的结果集求交集

                ids = ids.Intersect(LeaveIDs).ToList<string>();

                //本字段多行函数处理完成之后，如果结果集超过1个，继续按下一字体进行排除，反之，则退出循环，把这个唯一的返回出去

                if (ids.Count() <= 1) return string.Join(",", ids);
            }
            result = string.Join(",", ids);
            return result;
        }
    }
}
